package com.ruoyi.questionBank.service.impl;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.reader.MapSheetReader;
import com.alibaba.fastjson.JSON;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.ItemNotFoundException;
import com.ruoyi.common.utils.ObjectUtil;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.vo.PageResult;
import com.ruoyi.course.domain.SysCourseStudent;
import com.ruoyi.course.mapper.SysCourseStudentMapper;
import com.ruoyi.course.service.ISysCourseStudentService;
import com.ruoyi.exam.domain.Scores;
import com.ruoyi.exam.mapper.ScoresMapper;
import com.ruoyi.exam.vo.ExamPaperVO;
import com.ruoyi.exam.vo.ScoresVO;
import com.ruoyi.questionBank.domain.ExamPaper;
import com.ruoyi.questionBank.domain.Question;
import com.ruoyi.questionBank.mapper.ExamPaperMapper;
import com.ruoyi.questionBank.mapper.QuestionBankMapper;
import com.ruoyi.questionBank.mapper.QuestionMapper;
import com.ruoyi.questionBank.service.IQuestionBankService;
import com.ruoyi.questionBank.service.IQuestionService;
import com.ruoyi.questionBank.vo.CourseQuestionVO;
import com.ruoyi.questionBank.vo.QuestionAnswerVO;
import com.ruoyi.questionBank.vo.QuestionListVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
public class QuestionServiceImpl implements IQuestionService {
    @Autowired
    private QuestionMapper questionMapper;
    @Autowired
    private SysCourseStudentMapper sysCourseStudentMapper;
    @Autowired
    private ExamPaperMapper examPaperMapper;
    @Autowired
    private IQuestionBankService bankService;
    @Autowired
    private ISysCourseStudentService sysCourseStudentService;
    @Autowired
    private ScoresMapper scoresMapper;

    @Override
    public Question get(int qid) {
        return questionMapper.getById(qid);
    }

    @Override
    public List<Question> getEnable(Collection<Integer> qids) {
        if(qids == null || qids.isEmpty()){
            return Collections.emptyList();
        }
        return questionMapper.getByIdList(new ArrayList<>(qids));
    }

    @Override
    public List<Question> listRandomEnable() {
        List<Question> qlist = questionMapper.listAll();
        if(qlist == null || qlist.size() <= 0) {
            return new ArrayList<>();
        }
        //一套试卷40题，20道判断题，20道选择题
        List<Question> selectList = new ArrayList<>();
        List<Question> checkList = new ArrayList<>();
        qlist.forEach(item -> {
            if(item.getType() != null && (item.getType() == 1 || item.getType() == 2)) { //单选、多选
                selectList.add(item);
            }
            if (item.getType() != null && item.getType() == 3) {
                checkList.add(item);
            }
        });
        //
        Map<Integer,Question> resultMap = new HashMap<>();
        if (selectList.size() > 0) {
            resultMap.putAll(randomQuestion(selectList));
        }
        if (checkList.size() > 0) {
            resultMap.putAll(randomQuestion(checkList));
        }
        //
        List<Question> resultList = new ArrayList<>();
        resultList.addAll(resultMap.values());
        return resultList;
    }

    private Map<Integer,Question> randomQuestion(List<Question> qlist) {
        Map<Integer,Question> resultMap = new HashMap<>();
        if (qlist.size() <= 20) {
            qlist.forEach(item -> {
                resultMap.put(item.getId(),item);
            });
            return resultMap;
        }
        //
        int size = qlist.size();
        while (true) {
            if (resultMap.size() >= 20) {
                break;
            }
            Random random = new Random();
            int index = random.nextInt(size);
            if (resultMap.get(index) == null) {
                Question question = qlist.get(index);
                resultMap.put(question.getId(),question);
            }
        }
        //
        return resultMap;
    }

    @Override
    public int sizeQuestion(QuestionListVO listVO) {
        return questionMapper.size(listVO);
    }

    @Override
    public PageResult<Question> get(QuestionListVO listVO) {
        int total = questionMapper.size(listVO);
        PageResult<Question> pageResult = new PageResult<>(listVO.getPageNo(), listVO.getPageSize(), total);
        if (total > 0) {
            List<Question> list = questionMapper.listQuestion(listVO);
            pageResult.addAll(list);
        }
        return pageResult;
    }

    @Override
    public List<Question> list(QuestionListVO listVO) {
        List<Question> list = questionMapper.list(listVO);
        return list;
    }

    @Override
    @Transactional
    public Map<String, String> submitAnswer(ExamPaperVO examPaperVO) {
        ExamPaper examPaper = examPaperMapper.getById(examPaperVO.getPaperId());
        if (examPaper == null) {
            throw new ItemNotFoundException("试卷不存在");
        }
        List<Question> list = getEnable(examPaper.getQuestionIdList());
        Map<String,String> resultMap = checkAnswer(list,examPaperVO.getAnswers(),true);
        //
        Integer score = Integer.parseInt(resultMap.get("scores"));
        //
        LoginUser loginUser = SecurityUtils.getLoginUser();
        ScoresVO scoresVO = new ScoresVO();
        scoresVO.setExamPaperId(1); //写死关联1，确保所有人都是同一张试卷，实际上并不是
        scoresVO.setType(2);
        scoresVO.setUserId(loginUser.getUserId());
        List<Scores> scoresList = scoresMapper.listScores(scoresVO);
        if (CollectionUtils.isEmpty(scoresList)) {
            Scores scores = new Scores();
            scores.setScores(score);
            scores.setCreateTime(new Date());
            scores.setExamPaperId(1);//写死关联1，确保所有人都是同一张试卷，实际上并不是
            scores.setType(2);
            scores.setUpdateTime(scores.getCreateTime());
            scores.setUserId(loginUser.getUserId());
            scores.setExamCount(1);
            resultMap.put("examCount",String.valueOf(3 - scores.getExamCount()));
            scoresMapper.insertScores(scores);
        } else {
            if (scoresList.get(0).getExamCount() == null) {
                scoresList.get(0).setExamCount(0);
            }
            if (scoresList.get(0).getExamCount() >= 3) {
                throw new ItemNotFoundException("只能提交3次成绩");
            }
            if (scoresList.get(0).getScores() != null && scoresList.get(0).getScores() < score) {
                scoresList.get(0).setScores(score);
            }
            scoresList.get(0).setExamCount(scoresList.get(0).getExamCount()+1);
            resultMap.put("examCount",String.valueOf(3 - scoresList.get(0).getExamCount()));
            scoresMapper.updateScores(scoresList.get(0));
        }
        //
        return resultMap;
    }

    @Override
    @Transactional
    public Map<String, String> submitAnswer(CourseQuestionVO courseQuestionVO) {
        Map<String,String> resultMap = new HashMap<>();
        if (courseQuestionVO.getAnswers() != null && courseQuestionVO.getAnswers().size() > 0) {
            //获取试题列表
            QuestionListVO vo = new QuestionListVO();
            vo.setCourseNo(courseQuestionVO.getCourseNo());
            vo.setBankType(1);  //训练题库
            List<Question> list = questionMapper.list(vo);
            resultMap = checkAnswer(list,courseQuestionVO.getAnswers(),false);
        } else {
            resultMap.put("total","0");
            resultMap.put("right","0");
            resultMap.put("error","0");
            resultMap.put("scores",String.valueOf(courseQuestionVO.getScores()));
        }

        //
        Long score = Long.parseLong(resultMap.get("scores"));
//        if (score >= 60) {
            // 获取当前的用户
            LoginUser loginUser = SecurityUtils.getLoginUser();
            SysCourseStudent sysCourseStudent = sysCourseStudentMapper.getByUserIdAndCourseNo(loginUser.getUserId(),courseQuestionVO.getCourseNo());
            if (sysCourseStudent == null) {
                sysCourseStudent = new SysCourseStudent();
                sysCourseStudent.setUserId(loginUser.getUserId());
                sysCourseStudent.setStudentId(sysCourseStudent.getUserId());
                sysCourseStudent.setCourseNo(courseQuestionVO.getCourseNo());
                sysCourseStudent.setCreateTime(new Date());
            }
            sysCourseStudent.setScores(score);
            sysCourseStudent.setStudyStatus(3);
            sysCourseStudentService.updateSysCourseStudentProcess(sysCourseStudent);
//        }
        //
        return resultMap;
    }

    private Map<String,String> checkAnswer(List<Question> list,List<QuestionAnswerVO> answers,boolean exam) {
        ObjectUtil.checkNull(list ,"题目为空");
        ObjectUtil.checkNull(list ,"答案为空");
        Map<Integer,QuestionAnswerVO> answerVOMap = answers.stream().collect(Collectors.toMap(QuestionAnswerVO::getQuestionId, Function.identity(),(key1,key2) -> key1));
        //
        int right = 0;
        int examScore = 0;
        for (Question question : list) {
            QuestionAnswerVO answerVO = answerVOMap.get(question.getId());
            if (answerVO == null || StrUtil.isEmpty(answerVO.getAnswer())) {
                continue;
            }
            //一套试卷40题，20道判断题，每题2分，20道选择题，每题3分
            boolean result = question.answerResult(answerVO.getAnswer());
            if (result) {
                right++;
                if (question.getType() != null) {
                    if (question.getType() == 1 || question.getType() == 2) { //选择题
                        examScore += 3;
                    }
                    if (question.getType() == 3) { //判断题
                        examScore += 2;
                    }
                }
            }
        }
        //
        Map<String,String> resultMap = new HashMap<>();
        resultMap.put("total",String.valueOf(list.size()));
        resultMap.put("right",String.valueOf(right));
        resultMap.put("error",String.valueOf(list.size()-right));

        //
        if (exam) { //理论考试
            resultMap.put("scores", String.valueOf(examScore));
        } else {    //非理论考试，按平均算
            String scores = StringUtils.getPercentage((long)right,(long)list.size());
            Long score = 0L;
            try {
                Float f = Float.valueOf(scores);
                score = f.longValue();
            } catch (Exception e) {}
            resultMap.put("scores", String.valueOf(score));
        }

        //
        return resultMap;
    }

    @Override
    @Transactional
    public void add(Question question) {
        question.verifyComplete();
        question.setDefault();
        questionMapper.add(question);

        bankService.updateQuInsert();
    }



    @Override
    @Transactional
    public int importByFile(long createPerson, InputStream in) {
        List<Question> qs = buildQuestion(createPerson ,in);

        questionMapper.addList(qs);
        bankService.updateQuInsert();

        return qs.size();
    }


    private List<Question> buildQuestion(long createPerson, InputStream in){
        ExcelReader excelReader = ExcelUtil.getReader(in);

        MapSheetReader mapSheetReader = new MapSheetReader(1, 2, excelReader.getRowCount() - 3);

        List<Map<String, Object>> list = excelReader.read(mapSheetReader);

        List<Question> qs = list.stream().map(map -> {
            String str = JSON.toJSONString(map);

            Question question = JSON.parseObject(str , Question.class);
            question.setCreatePerson(createPerson);
            question.verifyComplete();
            question.setDefault();

            question.verifyAndRebuildAnswer();
            return question;
        }).collect(Collectors.toList());
        return qs;
    }

    @Override
    public void update(Question question) {
        if (question.getId() == null) {
            throw new IllegalArgumentException("id cannot be null");
        }
        questionMapper.update(question);

        bankService.updateQuUpdate();
    }

    @Override
    @Transactional
    public void del(int qid) {
        questionMapper.del(qid);

        bankService.updateQuDel();
    }

    @Override
    public void unEnable(int qid) {
        Question question = new Question();
        question.setId(qid);
        question.setEnable(false);
        questionMapper.update(question);

        bankService.updateQuEnable();
    }

    @Override
    public void enable(int qid) {
        Question question = new Question();
        question.setId(qid);
        question.setEnable(true);
        questionMapper.update(question);

        bankService.updateQuEnable();
    }
}
